"""
D5 插件功能演示模块
功能：实现与D5渲染器的插件交互，包括模型列表获取和界面交互
"""

import sys

# ==== 调试配置 ==== (生产环境应移除)
# import debugpy  # 调试模块应在正式发布时移除
# debugpy.connect(('localhost', 5678))  # 连接调试器

# ==== 日志重定向配置 ====
# LOG_FILE = open('D:/output.log', 'w', encoding='utf-8')  
# sys.stdout = LOG_FILE
# sys.stderr = LOG_FILE

import json
from pathlib import Path

# 第三方库导入分组
from PySide2.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, QFormLayout
from PySide2.QtCore import Qt, QStringListModel

# 本地模块导入分组
from D5Core.D5Tools import ModelList
from D5Core.D5Widget import D5Plugin
from D5Core.D5Models import D5Model
from D5Core.D5Common import *
from D5Core.D5Lights import PointLight


# 导入UI界面
import d5plugindemo
from PySide2.QtWidgets import QCheckBox

class D5PluginDemo(D5Plugin):
    def __init__(self,plugin_id):
        super().__init__(plugin_id)
        self.ui = d5plugindemo.Ui_D5PluginDemo()
        self.ui.setupUi(self)
        # 当前选中的模型
        self.current_model = None
        self.model_list = []
        
        # 连接信号和槽
        self.ui.GetModelsButton.clicked.connect(self.get_models)
        self.ui.ModelListView.clicked.connect(self.model_selected)
        self.ui.ClearLogButton.clicked.connect(self.clear_log)
        
        # 初始化列表模型
        self.list_model = QStringListModel()
        self.ui.ModelListView.setModel(self.list_model)
        
        # 用于存储参数控件的字典
        self.parameter_widgets = {}
        
        self.log("应用已启动。点击 'Get Models' 获取模型列表。")
    
    def log(self, message):
        """向日志区域添加消息"""
        self.ui.LogTextBrowser.append(message)
    
    def clear_log(self):
        """清空日志区域"""
        self.ui.LogTextBrowser.clear()
    
    def get_models(self):
        """获取D5中的所有模型"""
        self.log("正在获取模型列表...")
        model_list_map:dict[str,D5Model] = ModelList().get_model_list_map()
        self.model_list = []
        model_names = []

        for key, model in model_list_map.items():
            self.model_list.append({
                "id":key,
                "instance":model
            })
            model_names.append(model.get_name())
               
        # 更新列表视图
        self.list_model.setStringList(model_names)
        self.log(f"成功获取 {len(self.model_list)} 个模型。")
          
        
    
    def model_selected(self, index):
        """当选择模型列表中的一项时触发"""
        try:
            selected_index = index.row()
            if 0 <= selected_index < len(self.model_list):
                model_info = self.model_list[selected_index]                
                # 创建D5Model实例
                self.current_model = model_info['instance']
                
                # 显示模型参数
                self.create_parameter_form()
        except Exception as e:
            self.log(f"处理模型选择时出错: {str(e)}")
    
    def create_parameter_form(self):
        """根据当前模型的_attrs创建参数表单"""
        if not self.current_model:
            return
        
        # 清除现有参数控件
        for widget in self.parameter_widgets.values():
            for w in widget:
                w.deleteLater()
        self.parameter_widgets = {}
        
        # 清除布局中的所有项目
        while self.ui.paramFormLayout.rowCount() > 0:
            self.ui.paramFormLayout.removeRow(0)
        
        # 获取模型ID
        model_id = self.current_model.get_unique_actor_id()
        id_label = QLabel(f"{model_id}")
        self.ui.paramFormLayout.addRow("模型ID:", id_label)
        
        # 为每个属性创建表单项
        for attr_name, attr_config in self.current_model._attrs.items():
            # 创建标签
            label = QLabel(attr_name)
            
            # 获取属性值
            getter_method = getattr(self.current_model, f'get_{attr_name}')
            current_value = getter_method()
            
            # 创建输入控件
            value_widget = QLineEdit()

            
            # 根据属性类型设置显示的值
            if isinstance(current_value, Vector3):
                # 创建 x, y, z 输入框
                vector_layout = QHBoxLayout()
                
                x_input = QLineEdit()
                x_input.setText(str(current_value.x))
                x_input.setPlaceholderText("X")
                
                y_input = QLineEdit()
                y_input.setText(str(current_value.y))
                y_input.setPlaceholderText("Y")
                
                z_input = QLineEdit()
                z_input.setText(str(current_value.z))
                z_input.setPlaceholderText("Z")
                
                vector_layout.addWidget(QLabel("X:"))
                vector_layout.addWidget(x_input)
                vector_layout.addWidget(QLabel("Y:"))
                vector_layout.addWidget(y_input)
                vector_layout.addWidget(QLabel("Z:"))
                vector_layout.addWidget(z_input)
                
                value_container = QWidget()
                value_container.setLayout(vector_layout)
                
                # 使用组合字符串以便apply_parameter_change可以正确处理
                value_widget.setText(f"{current_value.x},{current_value.y},{current_value.z}")
                
                # 当x,y,z输入变化时更新文本框
                def update_vector():
                    try:
                        x = float(x_input.text()) if x_input.text() else 0
                        y = float(y_input.text()) if y_input.text() else 0
                        z = float(z_input.text()) if z_input.text() else 0
                        value_widget.setText(f"{x},{y},{z}")
                    except ValueError:
                        pass
                
                x_input.textChanged.connect(update_vector)
                y_input.textChanged.connect(update_vector)
                z_input.textChanged.connect(update_vector)
                
                # 使用控件容器代替简单的输入框
                control_layout = QHBoxLayout()
                control_layout.addWidget(value_container)
                control_layout.addWidget(value_widget)
                
                value_widget.hide()  # 隐藏组合文本框，但保持可访问性
            elif isinstance(current_value, LinearColor):
                # 创建 RGBA 输入框
                color_layout = QHBoxLayout()
                
                r_input = QLineEdit()
                r_input.setText(str(current_value.r))
                r_input.setPlaceholderText("R")
                
                g_input = QLineEdit()
                g_input.setText(str(current_value.g))
                g_input.setPlaceholderText("G")
                
                b_input = QLineEdit()
                b_input.setText(str(current_value.b))
                b_input.setPlaceholderText("B")
                
                a_input = QLineEdit()
                a_input.setText(str(current_value.a))
                a_input.setPlaceholderText("A")
                
                color_layout.addWidget(QLabel("R:"))
                color_layout.addWidget(r_input)
                color_layout.addWidget(QLabel("G:"))
                color_layout.addWidget(g_input)
                color_layout.addWidget(QLabel("B:"))
                color_layout.addWidget(b_input)
                color_layout.addWidget(QLabel("A:"))
                color_layout.addWidget(a_input)
                
                color_container = QWidget()
                color_container.setLayout(color_layout)
                
                # 使用组合字符串以便apply_parameter_change可以正确处理
                value_widget = QLineEdit()
                value_widget.setText(f"{current_value.r},{current_value.g},{current_value.b},{current_value.a}")
                
                # 当r,g,b,a输入变化时更新文本框
                def update_color():
                    try:
                        r = float(r_input.text()) if r_input.text() else 0
                        g = float(g_input.text()) if g_input.text() else 0
                        b = float(b_input.text()) if b_input.text() else 0
                        a = float(a_input.text()) if a_input.text() else 0
                        value_widget.setText(f"{r},{g},{b},{a}")
                    except ValueError:
                        pass
                
                r_input.textChanged.connect(update_color)
                g_input.textChanged.connect(update_color)
                b_input.textChanged.connect(update_color)
                a_input.textChanged.connect(update_color)
                
                # 使用控件容器代替简单的输入框
                control_layout = QHBoxLayout()
                control_layout.addWidget(color_container)
                control_layout.addWidget(value_widget)
                
                value_widget.hide()  # 隐藏组合文本框，但保持可访问性
                
            elif isinstance(current_value, bool):
                # 创建复选框
                
                checkbox = QCheckBox("启用")
                checkbox.setChecked(current_value)
                
                value_widget.setText(str(current_value).lower())
                
                # 当复选框状态改变时更新文本
                def update_bool(state):
                    value_widget.setText("true" if state == Qt.Checked else "false")
                
                checkbox.stateChanged.connect(update_bool)
                
                # 使用控件容器代替简单的输入框
                control_layout = QHBoxLayout()
                control_layout.addWidget(checkbox)
                control_layout.addWidget(value_widget)
                
                value_widget.hide()  # 隐藏文本框，但保持可访问性
                
            else:
                # 创建文本输入框
                value_widget.setText(str(current_value))
            
            # 创建应用按钮
            apply_button = QPushButton("应用")
            
            # 将属性名存储在按钮的属性中以供后续使用
            apply_button.setProperty("attr_name", attr_name)
            apply_button.clicked.connect(self.apply_parameter_change)
            
            # 添加到表单
            if isinstance(current_value, Vector3) or isinstance(current_value, bool) or isinstance(current_value, LinearColor):
                container = QWidget()
                container.setLayout(control_layout)
                control_layout.addWidget(apply_button)
                self.ui.paramFormLayout.addRow(label, container)
            else:
                # 标准文本输入的情况
                control_layout = QHBoxLayout()
                control_layout.addWidget(value_widget)
                control_layout.addWidget(apply_button)
                container = QWidget()
                container.setLayout(control_layout)
                self.ui.paramFormLayout.addRow(label, container)
            
            # 存储控件引用
            if isinstance(current_value, bool):
                self.parameter_widgets[attr_name] = [value_widget, apply_button, checkbox]  # 存储复选框引用
            else:
                self.parameter_widgets[attr_name] = [value_widget, apply_button]
        
    
    def apply_parameter_change(self):
        """当点击参数的应用按钮时触发，将修改应用到模型上"""
        try:
            sender = self.sender()
            attr_name = sender.property("attr_name")
            
            if not attr_name or attr_name not in self.parameter_widgets:
                return
            
            widgets = self.parameter_widgets[attr_name]
            input_widget = widgets[0]
            new_value_str = input_widget.text()
            
            # 获取属性配置
            attr_config = self.current_model._attrs[attr_name]
            
            # 对于布尔类型，直接使用复选框的状态
            if len(widgets) > 2 and isinstance(widgets[2], QCheckBox):
                checkbox = widgets[2]
                new_value = checkbox.isChecked()
                self.log(f"使用复选框状态：{new_value}")
            # 将输入值转换为正确的类型
            elif attr_config['from'] == Vector3.from_str:
                new_value = Vector3.from_str(new_value_str)
            elif 'from' in attr_config and callable(attr_config['from']):
                try:
                    # 尝试转换为布尔值
                    if attr_config['from'].__name__.startswith('<lambda>') and 'true' in str(attr_config['from']):
                        new_value = new_value_str.lower() == 'true'
                    else:
                        new_value = attr_config['from'](new_value_str)
                except:
                    self.log(f"无法将 '{new_value_str}' 转换为 {attr_name} 需要的类型")
                    return
            else:
                new_value = new_value_str
            
            # 获取setter方法
            setter_method = getattr(self.current_model, f'set_{attr_name}')
            
            # 应用更改
            success = setter_method(new_value)
            
            if success:
                self.log(f"成功更新属性 {attr_name} 为 {new_value}")
            else:
                self.log(f"更新属性 {attr_name} 失败")
                
        except Exception as e:
            self.log(f"应用参数更改时出错: {str(e)}")

def load_config(file_path):
    """加载插件配置"""
    config_path = Path(file_path)
    if not config_path.exists():
        raise FileNotFoundError(f"配置文件 {file_path} 不存在")
    
    try:
        with config_path.open('r', encoding='utf-8') as f:
            return json.load(f)
    except json.JSONDecodeError as e:
        print(f"JSON 解析错误: {e}")
        return {}  # 返回空字典可能导致后续问题，需要调用方处理

# 加载配置
plugin_dir = Path(__file__).parent
config = load_config(plugin_dir / "package.json")
plugin_id = config.get("id", "default")

# 创建插件实例
D5PluginDemo(plugin_id)

models:list[D5Model] = PointLight.create_light([Vector3(0,0,0)], "")

for model in models:
    model.set_hide(True)